package com.conph.rpc.core;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class RpcClientExecutor {
	private String rpcServerIp;//rpc服务器的信息
	private int rpcServerPort;
	private Gson gson;//网络信息均使用Gson格式的字符串进行发送
	private Class<?> returnType;//方法的返回值，用于得到结果的Gson转换
	
	RpcClientExecutor() {
		gson = new GsonBuilder().create();
	}

	RpcClientExecutor(String rpcServerIp, int rpcServerPort) {
		this();
		this.rpcServerIp = rpcServerIp;
		this.rpcServerPort = rpcServerPort;
	}

	String getRpcServerIp() {
		return rpcServerIp;
	}

	void setRpcServerIp(String rpcServerIp) {
		this.rpcServerIp = rpcServerIp;
	}

	int getRpcServerPort() {
		return rpcServerPort;
	}

	void setRpcServerPort(int rpcServerPort) {
		this.rpcServerPort = rpcServerPort;
	}
	
	public void setReturnType(Class<?> returnType) {
		this.returnType = returnType;
	}

	private void closeSocket(DataInputStream dis, DataOutputStream dos, Socket socket) {
		try {
			if (dis != null) {
				dis.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			dis = null;
		}
		try {
			if (dos != null) {
				dos.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			dos = null;
		}
		try {
			if (socket != null && !socket.isClosed()) {
				socket.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			socket = null;
		}
	}
	
	@SuppressWarnings("unchecked")
	<T> T rpcExecutor(String rpcBeanId, Object[] para) throws Exception {
		Socket socket = new Socket(rpcServerIp, rpcServerPort);
		DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
		if(para == null) {
			para = new Object[0];
		}
		String paraJson = gson.toJson(para);
		
		dos.writeUTF(rpcBeanId);
		dos.flush();

		DataInputStream dis = new DataInputStream(socket.getInputStream());
		dos.writeUTF(paraJson);
		String result = dis.readUTF();
		Object resObj = gson.fromJson(result, returnType);
		closeSocket(dis, dos, socket);
		
		return (T) resObj;
	}

}
